Poglobljena raziskava Tornada, spletnega ogrodja in asinhrone omrežne knjižnice v Pythonu. Naučite se graditi razširljive, visoko zmogljive aplikacije s podrobnimi razlagami, primeri in najboljšimi praksami.
Dokumentacija Tornado: Obsežen vodnik za razvijalce po vsem svetu
Tornado je spletno ogrodje v Pythonu in asinhrona omrežna knjižnica, prvotno razvita pri FriendFeed. Posebej je primeren za "long-polling", WebSockets in druge aplikacije, ki zahtevajo dolgotrajno povezavo z vsakim uporabnikom. Njegov neblokirajoči omrežni V/I (I/O) omogoča izjemno razširljivost in je močna izbira za gradnjo visoko zmogljivih spletnih aplikacij. Ta obsežen vodnik vas bo popeljal skozi osrednje koncepte Tornada in ponudil praktične primere za lažji začetek.
Kaj je Tornado?
V svojem jedru je Tornado spletno ogrodje in asinhrona omrežna knjižnica. Za razliko od tradicionalnih sinhronih spletnih ogrodij, Tornado uporablja arhitekturo z eno nitjo, ki temelji na zanki dogodkov. To pomeni, da lahko obravnava veliko sočasnih povezav, ne da bi potreboval nit za vsako povezavo, kar ga dela učinkovitejšega in bolj razširljivega.
Ključne značilnosti Tornada:
- Asinhrono omrežje: Jedro Tornada je zgrajeno okoli asinhronega V/I, kar mu omogoča učinkovito obravnavanje tisočih sočasnih povezav.
- Spletno ogrodje: Vključuje funkcije, kot so obravnavalci zahtevkov, usmerjanje, predloge in avtentikacija, kar ga dela za celovito spletno ogrodje.
- Podpora za WebSockets: Tornado ponuja odlično podporo za WebSockets, kar omogoča komunikacijo v realnem času med strežnikom in odjemalci.
- Lahek in hiter: Zasnovan za zmogljivost, je Tornado lahek in učinkovit, zmanjšuje obremenitev in povečuje prepustnost.
- Enostaven za uporabo: Kljub naprednim funkcijam je Tornado razmeroma enostaven za učenje in uporabo, z jasnim in dobro dokumentiranim API-jem.
Postavitev vašega okolja za Tornado
Preden se potopite v razvoj s Tornadom, morate nastaviti svoje okolje. Tukaj je vodnik po korakih:
- Namestite Python: Prepričajte se, da imate nameščen Python 3.6 ali novejšo različico. Prenesete ga lahko z uradne spletne strani Python (python.org).
- Ustvarite virtualno okolje (priporočeno): Uporabite
venv
alivirtualenv
za ustvarjanje izoliranega okolja za vaš projekt:python3 -m venv myenv source myenv/bin/activate # V Linuxu/macOSu myenv\Scripts\activate # V Windowsih
- Namestite Tornado: Namestite Tornado z uporabo pipa:
pip install tornado
Vaša prva aplikacija Tornado
Ustvarimo preprosto "Pozdravljen, svet!" aplikacijo s Tornadom. Ustvarite datoteko z imenom app.py
in dodajte naslednjo kodo:
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, World!")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
Sedaj zaženite aplikacijo iz vašega terminala:
python app.py
Odprite spletni brskalnik in pojdite na http://localhost:8888
. Videti bi morali sporočilo "Hello, World!".
Razlaga:
tornado.ioloop
: Osrednja zanka dogodkov, ki obravnava asinhrone operacije.tornado.web
: Zagotavlja komponente spletnega ogrodja, kot so obravnavalci zahtevkov in usmerjanje.MainHandler
: Obravnavalec zahtevkov, ki določa, kako obravnavati dohodne HTTP zahteve. Metodaget()
se kliče za zahteve GET.tornado.web.Application
: Ustvari aplikacijo Tornado, ki preslika URL vzorce v obravnavalce zahtevkov.app.listen(8888)
: Zažene strežnik, ki posluša za dohodne povezave na vratih 8888.tornado.ioloop.IOLoop.current().start()
: Zažene zanko dogodkov, ki obdeluje dohodne zahteve in upravlja asinhrone operacije.
Obravnavalci zahtevkov in usmerjanje
Obravnavalci zahtevkov so temelj spletnih aplikacij Tornado. Določajo, kako obravnavati dohodne HTTP zahteve glede na URL. Usmerjanje preslika URL-je v specifične obravnavalce zahtevkov.
Definiranje obravnavalcev zahtevkov:
Za ustvarjanje obravnavalca zahtevkov podedujte razred tornado.web.RequestHandler
in implementirajte ustrezne HTTP metode (get
, post
, put
, delete
, itd.).
class MyHandler(tornado.web.RequestHandler):
def get(self):
self.write("This is a GET request.")
def post(self):
data = self.request.body.decode('utf-8')
self.write(f"Received POST data: {data}")
Usmerjanje:
Usmerjanje se konfigurira pri ustvarjanju tornado.web.Application
. Podate seznam parov (tuple), kjer vsak par vsebuje URL vzorec in pripadajoči obravnavalec zahtevkov.
app = tornado.web.Application([
(r"/", MainHandler),
(r"/myhandler", MyHandler),
])
URL vzorci:
URL vzorci so regularni izrazi. Uporabite lahko skupine regularnih izrazov za zajemanje delov URL-ja in jih posredujete kot argumente metodam obravnavalca zahtevkov.
class UserHandler(tornado.web.RequestHandler):
def get(self, user_id):
self.write(f"User ID: {user_id}")
app = tornado.web.Application([
(r"/user/([0-9]+)", UserHandler),
])
V tem primeru se /user/([0-9]+)
ujema z URL-ji, kot je /user/123
. Del ([0-9]+)
zajame eno ali več števk in jih posreduje kot argument user_id
metodi get
razreda UserHandler
.
Predloge
Tornado vključuje preprost in učinkovit mehanizem za predloge. Predloge se uporabljajo za dinamično generiranje HTML-ja, ločevanje predstavitvene logike od aplikacijske logike.
Ustvarjanje predlog:
Predloge so običajno shranjene v ločenih datotekah (npr. index.html
). Tukaj je preprost primer:
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<h1>Welcome, {{ name }}!</h1>
<p>Today is {{ today }}.</p>
</body>
</html>
{{ name }}
in {{ today }}
sta označbi za mesta, ki bosta ob izrisovanju predloge zamenjani z dejanskimi vrednostmi.
Izrisovanje predlog:
Za izrisovanje predloge uporabite metodo render()
v vašem obravnavalcu zahtevkov:
class TemplateHandler(tornado.web.RequestHandler):
def get(self):
name = "John Doe"
today = "2023-10-27"
self.render("index.html", name=name, today=today)
Prepričajte se, da je nastavitev template_path
pravilno konfigurirana v nastavitvah vaše aplikacije. Privzeto Tornado išče predloge v imeniku z imenom templates
v istem imeniku kot vaša aplikacijska datoteka.
app = tornado.web.Application([
(r"/template", TemplateHandler),
], template_path="templates")
Sintaksa predlog:
Predloge v Tornadu podpirajo različne funkcije, vključno z:
- Spremenljivke:
{{ variable }}
- Kontrolni tok:
{% if condition %} ... {% else %} ... {% end %}
,{% for item in items %} ... {% end %}
- Funkcije:
{{ function(argument) }}
- Vključitve:
{% include "another_template.html" %}
- Ubežanje znakov (Escaping): Tornado samodejno ubeži HTML entitete, da prepreči napade skriptiranja med stranmi (XSS). Ubežanje lahko onemogočite z uporabo
{% raw variable %}
.
Asinhrone operacije
Moč Tornada je v njegovih asinhronih zmožnostih. Asinhrone operacije omogočajo vaši aplikaciji izvajanje neblokirajočega V/I, kar izboljša zmogljivost in razširljivost. To je še posebej uporabno za naloge, ki vključujejo čakanje na zunanje vire, kot so poizvedbe v bazi podatkov ali omrežne zahteve.
@tornado.gen.coroutine
:
Dekorator @tornado.gen.coroutine
vam omogoča pisanje asinhrone kode z uporabo ključne besede yield
. To omogoča, da asinhrona koda izgleda in se obnaša bolj kot sinhrona koda, kar izboljša berljivost in vzdrževanje.
import tornado.gen
import tornado.httpclient
class AsyncHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
http_client = tornado.httpclient.AsyncHTTPClient()
response = yield http_client.fetch("http://example.com")
self.write(response.body.decode('utf-8'))
V tem primeru je http_client.fetch()
asinhrona operacija, ki vrne Future
. Ključna beseda yield
zaustavi izvajanje korutine, dokler se Future
ne razreši. Ko je Future
razrešen, se korutina nadaljuje in telo odgovora se zapiše odjemalcu.
tornado.concurrent.Future
:
Future
predstavlja rezultat asinhrone operacije, ki morda še ni na voljo. Objekte Future
lahko uporabite za veriženje asinhronih operacij in obravnavanje napak.
tornado.ioloop.IOLoop
:
IOLoop
je srce asinhronega pogona Tornada. Spremlja datotečne deskriptorje in vtičnice za dogodke ter jih posreduje ustreznim obravnavalcem. Običajno vam ni treba neposredno komunicirati z IOLoop
, vendar je pomembno razumeti njegovo vlogo pri obravnavanju asinhronih operacij.
WebSockets
Tornado nudi odlično podporo za WebSockets, kar omogoča komunikacijo v realnem času med strežnikom in odjemalci. WebSockets so idealni za aplikacije, ki zahtevajo dvosmerno komunikacijo z nizko zakasnitvijo, kot so klepetalnice, spletne igre in nadzorne plošče v realnem času.
Ustvarjanje obravnavalca WebSocket:
Za ustvarjanje obravnavalca WebSocket podedujte razred tornado.websocket.WebSocketHandler
in implementirajte naslednje metode:
open()
: Kliče se, ko je vzpostavljena nova povezava WebSocket.on_message(message)
: Kliče se, ko je prejeto sporočilo od odjemalca.on_close()
: Kliče se, ko je povezava WebSocket zaprta.
import tornado.websocket
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
print("WebSocket odprt")
def on_message(self, message):
self.write_message(f"Poslali ste: {message}")
def on_close(self):
print("WebSocket zaprt")
def check_origin(self, origin):
return True # Omogoči med-izvorne WebSocket povezave
Integracija WebSocketov v vašo aplikacijo:
Dodajte obravnavalec WebSocket v konfiguracijo usmerjanja vaše aplikacije:
app = tornado.web.Application([
(r"/ws", WebSocketHandler),
])
Implementacija na strani odjemalca:
Na strani odjemalca lahko uporabite JavaScript za vzpostavitev povezave WebSocket in pošiljanje/prejemanje sporočil:
const websocket = new WebSocket("ws://localhost:8888/ws");
websocket.onopen = () => {
console.log("Povezava WebSocket vzpostavljena");
websocket.send("Pozdrav od odjemalca!");
};
websocket.onmessage = (event) => {
console.log("Prejeto sporočilo:", event.data);
};
websocket.onclose = () => {
console.log("Povezava WebSocket zaprta");
};
Avtentikacija in varnost
Varnost je ključni vidik razvoja spletnih aplikacij. Tornado ponuja več funkcij, ki vam pomagajo zavarovati vaše aplikacije, vključno z avtentikacijo, avtorizacijo in zaščito pred pogostimi spletnimi ranljivostmi.
Avtentikacija:
Avtentikacija je postopek preverjanja identitete uporabnika. Tornado ponuja vgrajeno podporo za različne sheme avtentikacije, vključno z:
- Avtentikacija na podlagi piškotkov: Shranjevanje uporabniških poverilnic v piškotke.
- Avtentikacija tretjih oseb (OAuth): Integracija s priljubljenimi socialnimi omrežji, kot so Google, Facebook in Twitter.
- Ključi API: Uporaba ključev API za avtentikacijo zahtevkov API.
Avtorizacija:
Avtorizacija je postopek določanja, ali ima uporabnik dovoljenje za dostop do določenega vira. Logiko avtorizacije lahko implementirate v svojih obravnavalcih zahtevkov, da omejite dostop na podlagi vlog ali dovoljenj uporabnikov.
Najboljše varnostne prakse:
- Zaščita pred skriptiranjem med stranmi (XSS): Tornado samodejno ubeži HTML entitete, da prepreči napade XSS. Vedno uporabljajte metodo
render()
za izrisovanje predlog in se izogibajte neposrednemu generiranju HTML-ja v obravnavalcih zahtevkov. - Zaščita pred ponarejanjem zahtev med stranmi (CSRF): Omogočite zaščito pred CSRF v nastavitvah vaše aplikacije, da preprečite napade CSRF.
- HTTPS: Vedno uporabljajte HTTPS za šifriranje komunikacije med strežnikom in odjemalci.
- Preverjanje vnosov: Preverite vse vnose uporabnikov, da preprečite napade z injiciranjem in druge ranljivosti.
- Redne varnostne revizije: Izvajajte redne varnostne revizije za odkrivanje in odpravljanje potencialnih ranljivosti.
Uvedba (Deployment)
Uvedba aplikacije Tornado vključuje več korakov, vključno s konfiguracijo spletnega strežnika, nastavitvijo upravitelja procesov in optimizacijo zmogljivosti.
Spletni strežnik:
Tornado lahko uvedete za spletnim strežnikom, kot sta Nginx ali Apache. Spletni strežnik deluje kot obratni proksi (reverse proxy) in posreduje dohodne zahteve aplikaciji Tornado.
Upravitelj procesov:
Upravitelj procesov, kot sta Supervisor ali systemd, se lahko uporablja za upravljanje procesa Tornado, kar zagotavlja, da se samodejno ponovno zažene, če se sesuje.
Optimizacija zmogljivosti:
- Uporabite zanko dogodkov, pripravljeno za produkcijo: Za izboljšano zmogljivost uporabite zanko dogodkov, kot je
uvloop
. - Omogočite stiskanje gzip: Omogočite stiskanje gzip, da zmanjšate velikost odgovorov HTTP.
- Predpomnite statične datoteke: Predpomnite statične datoteke, da zmanjšate obremenitev strežnika.
- Spremljajte zmogljivost: Spremljajte zmogljivost vaše aplikacije z orodji, kot sta New Relic ali Prometheus.
Internacionalizacija (i18n) in lokalizacija (l10n)
Pri gradnji aplikacij za globalno občinstvo je pomembno upoštevati internacionalizacijo (i18n) in lokalizacijo (l10n). i18n je proces oblikovanja aplikacije tako, da jo je mogoče brez inženirskih sprememb prilagoditi različnim jezikom in regijam. l10n je proces prilagajanja internacionalizirane aplikacije za določen jezik ali regijo z dodajanjem lokalno specifičnih komponent in prevajanjem besedila.
Tornado in i18n/l10n
Tornado sam po sebi nima vgrajenih knjižnic za i18n/l10n. Vendar pa lahko enostavno integrirate standardne knjižnice Pythona, kot je `gettext`, ali bolj sofisticirana ogrodja, kot je Babel, za obravnavo i18n/l10n znotraj vaše aplikacije Tornado.
Primer z uporabo `gettext`:
1. **Nastavite svoje lokalizacije:** Ustvarite imenike za vsak jezik, ki ga želite podpreti, ki vsebujejo kataloge sporočil (običajno datoteke `.mo`).
locales/
en/LC_MESSAGES/messages.mo
fr/LC_MESSAGES/messages.mo
de/LC_MESSAGES/messages.mo
2. **Izvlecite prevodljive nize:** Uporabite orodje, kot je `xgettext`, da izvlečete prevodljive nize iz vaše kode Python v datoteko `.po` (Portable Object). Ta datoteka bo vsebovala originalne nize in označbe za prevode.
xgettext -d messages -o locales/messages.po your_tornado_app.py
3. **Prevedite nize:** Prevedite nize v datotekah `.po` za vsak jezik.
4. **Prevedite prevode:** Prevedite datoteke `.po` v datoteke `.mo` (Machine Object), ki jih `gettext` uporablja med izvajanjem.
msgfmt locales/fr/LC_MESSAGES/messages.po -o locales/fr/LC_MESSAGES/messages.mo
5. **Integrirajte v vašo aplikacijo Tornado:**
import gettext
import locale
import os
import tornado.web
class BaseHandler(tornado.web.RequestHandler):
def initialize(self):
try:
locale.setlocale(locale.LC_ALL, self.get_user_locale().code)
except locale.Error:
# Obravnavanje primerov, ko lokalizacija ni podprta s strani sistema
print(f"Lokalizacija {self.get_user_locale().code} ni podprta")
translation = gettext.translation('messages', 'locales', languages=[self.get_user_locale().code])
translation.install()
self._ = translation.gettext
def get_current_user_locale(self):
# Logika za določanje uporabnikove lokalizacije (npr. iz glave Accept-Language, uporabniških nastavitev itd.)
# To je poenostavljen primer - potrebovali boste bolj robustno rešitev
accept_language = self.request.headers.get('Accept-Language', 'en')
return tornado.locale.get(accept_language.split(',')[0].split(';')[0])
class MainHandler(BaseHandler):
def get(self):
self.render("index.html", _=self._)
settings = {
"template_path": os.path.join(os.path.dirname(__file__), "templates"),
}
app = tornado.web.Application([
(r"/", MainHandler),
], **settings)
6. **Spremenite svoje predloge:** Uporabite funkcijo `_()` (povezano z `gettext.gettext`), da označite nize za prevajanje v svojih predlogah.
<h1>{{ _("Dobrodošli na naši spletni strani!") }}</h1>
<p>{{ _("To je preveden odstavek.") }}</p>
Pomembni premisleki za globalno občinstvo:
- **Kodiranje znakov:** Vedno uporabljajte kodiranje UTF-8 za podporo širokemu naboru znakov.
- **Formatiranje datuma in časa:** Uporabite lokalno specifično formatiranje datuma in časa. Funkciji `strftime` in `strptime` v Pythonu se lahko uporabljata z nastavitvami lokalizacije.
- **Formatiranje številk:** Uporabite lokalno specifično formatiranje številk (npr. decimalna ločila, ločila tisočic). Modul `locale` ponuja funkcije za to.
- **Formatiranje valut:** Uporabite lokalno specifično formatiranje valut. Razmislite o uporabi knjižnice, kot je `Babel`, za naprednejše upravljanje valut.
- **Jeziki z desne na levo (RTL):** Podprite jezike RTL, kot sta arabščina in hebrejščina. To lahko vključuje zrcaljenje postavitve vaše spletne strani.
- **Kakovost prevodov:** Uporabite profesionalne prevajalce za zagotavljanje natančnih in kulturno primernih prevodov. Strojno prevajanje je lahko dober začetek, vendar pogosto zahteva človeški pregled.
- **Zaznavanje lokalizacije uporabnika:** Implementirajte robustno zaznavanje lokalizacije na podlagi uporabniških preferenc, nastavitev brskalnika ali IP naslova. Uporabnikom omogočite ročno izbiro želenega jezika.
- **Testiranje:** Temeljito testirajte svojo aplikacijo z različnimi lokalizacijami, da zagotovite, da je vse pravilno prikazano.
Napredne teme
Strani z napakami po meri:
Prilagodite lahko strani z napakami, ki jih Tornado prikaže, ko pride do napake. To vam omogoča, da zagotovite bolj uporabniku prijazno izkušnjo in vključite informacije za odpravljanje napak.
Nastavitve po meri:
V konfiguraciji aplikacije lahko definirate nastavitve po meri in do njih dostopate v svojih obravnavalcih zahtevkov. To je uporabno za shranjevanje parametrov, specifičnih za aplikacijo, kot so povezovalni nizi za bazo podatkov ali ključi API.
Testiranje:
Temeljito testirajte svoje aplikacije Tornado, da zagotovite njihovo pravilno in varno delovanje. Uporabite enotske teste, integracijske teste in teste od konca do konca, da pokrijete vse vidike vaše aplikacije.
Zaključek
Tornado je močno in vsestransko spletno ogrodje, ki je zelo primerno za gradnjo razširljivih, visoko zmogljivih spletnih aplikacij. Njegova asinhrona arhitektura, podpora za WebSockets in enostaven API ga delajo za priljubljeno izbiro med razvijalci po vsem svetu. Z upoštevanjem smernic in primerov v tem obsežnem vodniku lahko začnete graditi lastne aplikacije Tornado in izkoristite njegove številne funkcije.
Ne pozabite se posvetovati z uradno dokumentacijo Tornada za najnovejše informacije in najboljše prakse. Veselo kodiranje!